import logging

import docker
from docker.models.containers import Container
from docker.errors import ImageNotFound

from utils.utils import *

logger = logging.getLogger()

# 1, pull baseimage
# 2, run baseimage
# 3, run init commands
# 4, run yum-install commands
# 5, commit container to tmp1Image
# 6, remove container
# 7, run build to tmp2image
# 8, run tmp2image
# 9, run pip-install commands
# 10, commit container to target name
# 11, remove container

class Mkcidocker(object):

    def __init__(self, base_image: str, conf_dir: str) -> None:
        self.base_image = base_image
        self.conf_dir = conf_dir
        self.tmp_confg = os.path.join(conf_dir,'mkcidocker.yaml')
        self.dockerfile = os.path.join(conf_dir, 'ci_dockerfile')

    @staticmethod
    def separate_image_str(base_image:str):
        str_split = base_image.split(':')
        if len(str_split) >= 2:
            return str_split[0],str_split[1]
        return str_split[0], 'latest'

    def exec(self, target_img):
        client = docker.from_env()
        
        logger.info('# 1, pull baseimage')
        repository, tag = self.separate_image_str(self.base_image)
        logger.info("# 1, pull base image:{}:{}".format(repository, tag))
        client.images.pull(repository=repository, tag=tag)
        logger.info("# 1, pull baseimage finished")


        logger.info("# 2, run baseimage")
        container = client.containers.run(
            image=self.base_image,
            detach=True,
            tty=True
        )
        logger.info("# 2, run baseimage finished")


        logger.info('# 3, run init commands')
        command_list = [
            "userdel -r openeuler",
            "sed -i 's/repo.openeuler.org/mirrors.huaweicloud.com\/openeuler/g' /etc/yum.repos.d/openEuler.repo",
            "sed -i 's/TMOUT=300/TMOUT=/g' /etc/bashrc",
            "chmod -R 777 /opt/buildtools/nativesdk",
            "sed -i 's/openeuler/root/g' /etc/sudoers",
            "yum update -y",
        ]
        for cmd in command_list:
            res = container.exec_run(
                cmd = cmd,
                stdout=True,
                stderr=True,
                stream=True,
            )
            for line in res.output:
                logger.info(line.decode())
        logger.info('# 3, run init commands finished')

        confs = param_yaml(self.tmp_confg)

        logger.info('# 4, run yum-install commands')
        cmd = 'yum install '
        for repo in confs['yum-install']:
            cmd += repo['name'] + ' '
        cmd += '-y'
        res = container.exec_run(
            cmd=cmd,
            stdout=True,
            stderr=True,
            stream=True
        )
        for line in res.output:
            logger.info(line.decode())
        logger.info('# 4, run yum-install commands finished')


        logger.info('# 5, commit container to tmp1Image')
        repoName = generate_random_str(6).lower()
        tag = 'latest'
        tmp1ImageStr = repoName + ':' + tag
        logger.info('beginning commit image:{}'.format(tmp1ImageStr))
        container.commit(tmp1ImageStr)
        logger.info('commit image: {} fininsh'.format(tmp1ImageStr))
        logger.info('# 5, commit container to tmp1Image finished')


        logger.info('# 6, remove container')
        container.stop()
        container.remove()
        logger.info('# 6, remove container finished')

        
        dockerfileDir = os.path.join(os.path.dirname(__file__),'Dockerfile')
        logger.info('# 7, run build to tmp2image')
        with open(self.dockerfile, 'r') as rf:
            data = rf.read()
            dockerFileStr = 'from ' + tmp1ImageStr + '\n' + data
            if not os.path.exists(dockerfileDir):
                os.mknod(dockerfileDir)
            with open(dockerfileDir, 'w') as wf:
                wf.write(dockerFileStr)

        buildout = client.images.build(path=os.path.dirname(dockerfileDir))
        tmp2image = buildout[0]
        logger.info('tm2image is {}'.format(tmp2image.short_id))
        for line in buildout[1]:
            logger.info(line)
        logger.info('# 7, run build to tmp2image finished')

        logger.info('# 8, run tmp2image')
        container = client.containers.run(
            image=tmp2image.short_id,
            command='bash',
            user='jenkins',
            detach=True,
            tty=True
        )
        logger.info('# 8, run tmp2image finished')

        logger.info('# 9, run pip-install commands')
        after = ''
        if 'pip-mirror' in confs:
            after = ' -i ' + confs['pip-mirror']
        for pip in confs['pip-install']:
            while True:
                cmd = 'sudo pip install ' + pip['name'] + after
                logger.info('cmd is {}'.format(cmd))
                res = container.exec_run(
                    cmd=cmd,
                    user='jenkins',
                    stdout=True,
                    stderr=True,
                    stream=True
                )
                isError=False
                for line in res.output:
                    logger.info(line.decode())
                    if 'ERROR' in line.decode():
                        isError = True
                if not isError:
                    break
                    
        logger.info('container is {}'.format(container.short_id))
        
        logger.info('# 9, run pip-install commands finished')

        logger.info('# 10, commit container to target name')
        container.commit(target_img)
        logger.info('# 10, commit container to target name finished')
        
        logger.info('# 11, remove container')
        container.stop()
        container.remove()
        logger.info('# 11, remove container finished')

        logger.info("======================================================")
        logger.info("build {} successful".format(target_img))
        logger.info("======================================================")
        